'''
Created on 26/10/2009

@author: eh01
'''
from datastore.database import DataStore
from datastore.resource import ResourceDict, Resource
from runtime.task import Task
import logging

class NotificationTask(Task):
    '''
    Notification Task allows users to monitor the notifications for them coming from SPEAR.
    '''
    
    def cb_start(self, method, uri, res, result, context, **kwargs):
        '''
        Implementation of the start method
        '''
        uri_reference = context.uri('reference:')
        context.watch_all(['put'], uri_reference.notification.collection(True), 'cb_monitor_notification')
        context.watch_all(['delete'], uri_reference.notification.collection(True), 'cb_stop_monitor_notification')
        self.notifications = {}
    
    def cb_monitor_notification(self, method, uri, new_uri, result, spaces_context, **kwargs):
        '''
        Creates a cron job to monitor notifications.
        '''
        uri_time = spaces_context.uri('time:')
        notification_res = spaces_context.get(new_uri)
        cron_res = Resource()
        # check notifications every 10 secs
        cron_res.interval = notification_res.interval
        # create a cron job
        cron_uri = spaces_context.put(uri_time.cron.collection(True), cron_res)
        # watch the cron job uri
        watch_ref = spaces_context.watch(['put'], cron_uri.pop, 'cb_issue_notification', notification_res=notification_res)
        # save cron_uri and watch_ref together so they can be deleted
        self.notifications[new_uri] = (cron_uri, watch_ref)
    
    def cb_stop_monitor_notification(self, method, uri, res, result, spaces_context, **kwargs):
        (cron_uri, watch_ref) = self.notifications[uri]
        spaces_context.delete(cron_uri)
        spaces_context.delete_watch(watch_ref)
            
    def cb_issue_notification(self, method, uri, res, result, spaces_context, **kwargs):
        '''
        Issues a call to SPEAR to retrieve notifications.
        '''
#        self.log('cb_issue_notification', logging.INFO)
        uri_a2a = spaces_context.uri('a2a:')
        uri_spear = spaces_context.uri('spear:')
        uri_datastore = spaces_context.uri('datastore:')
        ds = DataStore(spaces_context.spaces.ns)
        notification_res = kwargs['notification_res']
        access_token = ds.find([(uri_datastore.resource.type, uri_spear.type.pvtaccesstoken)])[0]        
        request_res = self.create_lxspearnotification_getnotification_request_data(notification_res.environment, access_token)
        # issue a call to SPEAR and set the callback
        new_uri = spaces_context.put(uri_a2a.ws.LxSpearNotification_2_2.getNotification, request_res)
        spaces_context.get_wait(new_uri.response, 'cb_parse_lxspearnotification_2_2_getNotification_response', **kwargs)     
    
    def cb_parse_lxspearnotification_2_2_acknowledge_response(self, method, uri, res, result, spaces_context, **kwargs):
        '''
        Parse the response from SPEAR.
        '''
        # get the response
        response = res
        self.log('Acknowledge resposne', logging.DEVEL)
        self.log(response, logging.DEVEL)
        if response.acknowledgeResponse.acknowledgeReturn.responseType.code == '000':
            self.log('NOTIFICATION ACKNOWLEDGED', logging.INFO)
    
    def cb_parse_lxspearnotification_2_2_getNotification_response(self, method, uri, res, result, spaces_context, **kwargs):
        '''
        Parse the response from SPEAR.
        '''
        # get the response
        response = res
        notification_res = kwargs['notification_res']
        if 'notifications' in response.getNotificationResponse.getNotificationReturn:
            self.log(response, logging.DEVEL)      
            notifications = response.getNotificationResponse.getNotificationReturn.notifications
            self.log('{0} NOTIFICATIONS'.format(len(notifications)), logging.INFO)
            count = 0
            for notification in notifications:
                count += 1
                self.log('NOTIFICATION #{0}'.format(count), logging.INFO)              
                self.log('{0} {1} {2} {3} {4} {5}'.format(notification.id, notification.event, notification.documentType, notification.type, notification.spearReferenceNumber, notification.subject), logging.INFO)
                self.issue_ack_notification(spaces_context, notification.id, notification_res)
        else:
            self.log('NO NOTIFICATIONS', logging.INFO)            
    
    def issue_ack_notification(self, spaces_context, notification_id, notification_res):
        '''
        Issues a call to SPEAR to retrieve notifications.
        '''
#        self.log('cb_issue_notification', logging.INFO)
        uri_a2a = spaces_context.uri('a2a:')
        uri_spear = spaces_context.uri('spear:')
        uri_datastore = spaces_context.uri('datastore:')
        ds = DataStore(spaces_context.spaces.ns)
        access_token = ds.find([(uri_datastore.resource.type, uri_spear.type.pvtaccesstoken)])[0]        
        request_res = self.create_lxspearnotification_acknowledge_request_data(notification_res.environment, access_token, notification_id)
        # issue a call to SPEAR and set the callback
        new_uri = spaces_context.put(uri_a2a.ws.LxSpearNotification_2_2.acknowledge, request_res)
        spaces_context.get_wait(new_uri.response, 'cb_parse_lxspearnotification_2_2_acknowledge_response')
    
    def create_lxspearnotification_acknowledge_request_data(self, environment, access_token, notification_id):
        '''
        Creates the LxSpearNotification acknowledge request data resource. 
        '''
        webservice_parameter = ResourceDict()
        acknowledge = [] 
        webservice_parameter.acknowledge = acknowledge 
        access_token_elements = self.create_access_token(access_token)
        accessToken = ResourceDict()        
        accessToken.accessToken = access_token_elements
        notificationid = ResourceDict()
        notificationid.notificationid = notification_id
        acknowledge.extend([accessToken, notificationid])
        res = Resource()
        res.data = webservice_parameter
        res.environment = environment        
        return res
    
    def create_lxspearnotification_getnotification_request_data(self, environment, access_token):
        '''
        Creates the LxSpearNotification getNotification request data resource. 
        '''
        webservice_parameter = ResourceDict()
        getNotification = [] 
        webservice_parameter.getNotification = getNotification 
        access_token_elements = self.create_access_token(access_token)
        accessToken = ResourceDict()        
        accessToken.accessToken = access_token_elements
        getNotification.extend([accessToken])
        res = Resource()
        res.data = webservice_parameter
        res.environment = environment        
        return res        
    
    def create_access_token(self, access_token):
        '''
        Creates the Access Token resource.
        '''
        element_1 = ResourceDict()
        element_1.accessLevel = access_token.spear_user_access_level
        element_2 = ResourceDict()
        element_2.hostId = access_token.spear_user_username
        element_3 = ResourceDict()
        element_3.hostPassword = access_token.spear_user_password
        element_4 = ResourceDict()
        element_4.remoteUser = access_token.spear_user_remote_user
        access_token_list = [element_1, element_2, element_3, element_4]
        return access_token_list